home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dutil / loadabs.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  7KB  |  426 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  LOADABS.C
  9.  *
  10.  *  loadabs exefile -o outfile -A addr
  11.  *
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17.  
  18. #ifdef AMIGA
  19. #include <lib/version.h>
  20. #else
  21. #include <include/lib/version.h>
  22. #endif
  23.  
  24. #define HUNK_BSS    0x3EB
  25. #define HUNK_CODE    0x3E9
  26. #define HUNK_DATA    0x3EA
  27. #define HUNK_RELOC32    0x3EC
  28. #define HUNK_SYMBOLS    0x3F0
  29. #define HUNK_END    0x3F2
  30. #define HUNK_HEAD    0x3F3
  31.  
  32. IDENT("loadabs",".3");
  33. DCOPYRIGHT;
  34.  
  35. long    NumHunks;
  36. long    FirstHunk;
  37. long    LastHunk;
  38.  
  39. short    DDebug;
  40.  
  41. typedef unsigned char ubyte;
  42.  
  43. typedef struct {
  44.     long    Type;
  45.     long    Len;
  46.     long    Pc;
  47.     char    *Data;
  48. } Hunk;
  49.  
  50. Hunk    *Hunks;
  51.  
  52. long    fgetl(FILE *);
  53. void    LoadHeaderInfo(FILE *);
  54. void    ScanHunks(FILE *, long);
  55. void    RelocHunks(FILE *);
  56. void    DumpHunks(FILE *);
  57.  
  58. main(ac, av)
  59. char *av[];
  60. {
  61.     short i;
  62.     char *inFile = NULL;
  63.     char *outFile= NULL;
  64.     FILE *fi;
  65.     FILE *fo;
  66.     long scanPc;
  67.  
  68.     if (ac == 1) {
  69.         puts(Ident);
  70.         puts(DCopyright);
  71.     puts("LoadAbs exefile -o outfile -A begaddr -d[#]");
  72.     exit(1);
  73.     }
  74.  
  75.     for (i = 1; i < ac; ++i) {
  76.     char *ptr = av[i];
  77.  
  78.     if (*ptr != '-') {
  79.         if (inFile) {
  80.         puts("input file specified twice!");
  81.         exit(1);
  82.         }
  83.         inFile = ptr;
  84.         continue;
  85.     }
  86.     ptr += 2;
  87.  
  88.     switch(ptr[-1]) {
  89.     case 'o':
  90.         if (outFile) {
  91.         puts("output file specified twice!");
  92.         exit(1);
  93.         }
  94.         outFile = (*ptr) ? ptr : av[++i];
  95.         break;
  96.     case 'A':
  97.         scanPc = strtol((*ptr) ? ptr : av[++i], NULL, 0);
  98.         break;
  99.     case 'd':
  100.         if (*ptr == 0)
  101.         DDebug = 1;
  102.         else
  103.         DDebug = atoi(ptr);
  104.         break;
  105.     default:
  106.         printf("Bad option: %s\n", av[i]);
  107.         exit(1);
  108.     }
  109.     }
  110.     if (i > ac) {
  111.     puts("expected argument");
  112.     exit(1);
  113.     }
  114.     if (inFile == NULL) {
  115.     puts("no input executable specified");
  116.     exit(1);
  117.     }
  118.     if (outFile == NULL) {
  119.     puts("no output image file specified");
  120.     exit(1);
  121.     }
  122.     if ((fi = fopen(inFile, "r")) == NULL) {
  123.     puts("unable to open input file");
  124.     exit(1);
  125.     }
  126.     if (fgetl(fi) != HUNK_HEAD) {
  127.     puts("Not an executable");
  128.     exit(1);
  129.     }
  130.  
  131.     /*
  132.      *    skip name
  133.      */
  134.     {
  135.     int n = fgetl(fi);
  136.     while (n--)
  137.         fgetl(fi);
  138.     }
  139.  
  140.     /*
  141.      *    header info
  142.      */
  143.  
  144.     NumHunks    = fgetl(fi);
  145.     FirstHunk    = fgetl(fi);
  146.     LastHunk    = fgetl(fi);
  147.  
  148.     Hunks = malloc(NumHunks * sizeof(Hunk));
  149.     if (Hunks == NULL) {
  150.     puts("malloc failed");
  151.     exit(1);
  152.     }
  153.     LoadHeaderInfo(fi);
  154.     {
  155.     long pos = ftell(fi);
  156.     if (DDebug)
  157.         puts("scan");
  158.  
  159.     ScanHunks(fi, scanPc);
  160.  
  161.     fseek(fi, pos, 0);
  162.     if (DDebug)
  163.         puts("reloc");
  164.  
  165.     RelocHunks(fi);
  166.     }
  167.     fclose(fi);
  168.  
  169.     if ((fo = fopen(outFile, "w")) == NULL) {
  170.     puts("unable to create image file");
  171.     exit(1);
  172.     }
  173.     if (DDebug)
  174.     puts("dump");
  175.     DumpHunks(fo);
  176.     fclose(fo);
  177.     return(0);
  178. }
  179.  
  180. void
  181. LoadHeaderInfo(fi)
  182. FILE *fi;
  183. {
  184.     int n;
  185.     Hunk *h;
  186.  
  187.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  188.     h->Len = fgetl(fi) * 4;
  189.     h->Data= malloc(h->Len + 1);    /*  +1 so can malloc 0 wo/error    */
  190.     if (h->Data == NULL) {
  191.         printf("malloc failed hunk %d (%d)\n", n, h->Len);
  192.         exit(1);
  193.     }
  194.     clrmem(h->Data, h->Len);
  195.     }
  196. }
  197.  
  198. void
  199. ScanHunks(fi, pc)
  200. FILE *fi;
  201. long pc;
  202. {
  203.     int n;
  204.     Hunk *h;
  205.  
  206.     n = 0;
  207.     h = Hunks;
  208.  
  209.     while (n < NumHunks) {
  210.     long len;
  211.     long t = fgetl(fi);
  212.  
  213.     if (DDebug)
  214.         printf("Header %08lx\n", t);
  215.  
  216.     switch(t) {
  217.     case HUNK_BSS:
  218.         h->Type = t;
  219.         fgetl(fi);        /*    skip length */
  220.         break;
  221.     case HUNK_CODE:
  222.     case HUNK_DATA:
  223.         h->Type = t;
  224.         len = fgetl(fi) * 4;
  225.         if (len > h->Len || len < 0) {
  226.         printf("Hunk Error: Text len %d/%d\n", len, h->Len);
  227.         exit(1);
  228.         }
  229.         if (fread(h->Data, 1, len, fi) != len) {
  230.         puts("Unexpected EOF");
  231.         exit(1);
  232.         }
  233.         break;
  234.     case HUNK_RELOC32:
  235.         while (len = fgetl(fi) * 4) {
  236.         if (DDebug)
  237.             printf("len = %d\n", len);
  238.         fgetl(fi);    /*  skip hunk#    */
  239.         fseek(fi, len, 1);
  240.         }
  241.         break;
  242.     case HUNK_SYMBOLS:
  243.         /*
  244.          *    ignore
  245.          */
  246.         while (len = fgetl(fi)) {
  247.         ubyte type = len >> 24;
  248.  
  249.         len &= 0x00FFFFFF;
  250.         fseek(fi, len * 4, 1);
  251.  
  252.         switch(type) {
  253.         case 0:     /*  SYMB    */
  254.         case 1:     /*  DEF     */
  255.         case 2:     /*  ABS     */
  256.         case 3:     /*  RES     */
  257.             fgetl(fi);
  258.             break;
  259.         case 130:    /*  COMMON  */
  260.             puts("COMMON symbol not supported");
  261.             fgetl(fi);    /*  skip common size */
  262.             /* fall through */
  263.         case 129:    /*  REF32   */
  264.         case 131:    /*  REF16   */
  265.         case 132:    /*  REF8    */
  266.         case 134:    /*  REF16D  */
  267.                 /*  skip relocation info */
  268.             fseek(fi, fgetl(fi) * 4 + 4, 1);
  269.             break;
  270.         default:
  271.             printf("Symbol type %d unknown\n", type);
  272.             exit(1);
  273.         }
  274.         }
  275.         break;
  276.     case HUNK_END:
  277.         ++n;
  278.         ++h;
  279.         break;
  280.     default:
  281.         printf("Hunk type %08lx unknown\n", h->Type);
  282.         exit(1);
  283.     }
  284.     }
  285.  
  286.     /*
  287.      *    setup PC start locations for hunks
  288.      */
  289.  
  290.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  291.     h->Pc = pc;
  292.     pc += h->Len;
  293.     }
  294. }
  295.  
  296. void
  297. RelocHunks(fi)
  298. FILE *fi;
  299. {
  300.     int n;
  301.     int dhno;
  302.     Hunk *h;
  303.     Hunk *dh;
  304.  
  305.     n = 0;
  306.     h = Hunks;
  307.  
  308.     while (n < NumHunks) {
  309.     long len;
  310.     long t;
  311.  
  312.     t = fgetl(fi);
  313.     switch(t) {
  314.     case HUNK_BSS:
  315.         fgetl(fi);    /*  skip length */
  316.         break;
  317.     case HUNK_CODE:
  318.     case HUNK_DATA:
  319.         len = fgetl(fi) * 4;
  320.         fseek(fi, len, 1);
  321.         break;
  322.     case HUNK_RELOC32:
  323.         while (len = fgetl(fi)) {
  324.         dhno = fgetl(fi);    /*  hunk to relocate to */
  325.         if (dhno < FirstHunk || dhno >= NumHunks + FirstHunk) {
  326.             printf("hunk# in reloc32 oob: %d/%d\n", dhno, NumHunks);
  327.             exit(1);
  328.         }
  329.         dh = Hunks + dhno - FirstHunk;
  330.         while (len) {        /*  offsets to relocate */
  331.             long off = fgetl(fi);
  332.  
  333.             if (off < 0 || off > h->Len - 4) {
  334.             printf("Offset out of bounds: %d/%d\n", off, h->Len);
  335.             exit(1);
  336.             }
  337.             *(long *)(h->Data + off) += dh->Pc;
  338.             if (DDebug)
  339.             printf("Reloc in %d to %d offset %d add %04x\n", n, dhno, off, dh->Pc);
  340.             --len;
  341.         }
  342.         }
  343.         break;
  344.     case HUNK_SYMBOLS:
  345.         /*
  346.          *    ignore
  347.          */
  348.         while (len = fgetl(fi)) {
  349.         ubyte type = len >> 24;
  350.  
  351.         len &= 0x00FFFFFF;
  352.         fseek(fi, len * 4, 1);
  353.  
  354.         switch(type) {
  355.         case 0:     /*  SYMB    */
  356.         case 1:     /*  DEF     */
  357.         case 2:     /*  ABS     */
  358.         case 3:     /*  RES     */
  359.             fgetl(fi);
  360.             break;
  361.         case 130:    /*  COMMON  */
  362.             puts("COMMON symbol not supported");
  363.             fgetl(fi);    /*  skip common size */
  364.             /* fall through */
  365.         case 129:    /*  REF32   */
  366.         case 131:    /*  REF16   */
  367.         case 132:    /*  REF8    */
  368.         case 134:    /*  REF16D  */
  369.                 /*  skip relocation info */
  370.             fseek(fi, fgetl(fi) * 4 + 4, 1);
  371.             break;
  372.         default:
  373.             printf("Symbol type %d unknown\n", type);
  374.             exit(1);
  375.         }
  376.         }
  377.         break;
  378.     case HUNK_END:
  379.         ++n;
  380.         ++h;
  381.         break;
  382.     default:
  383.         printf("Hunk type %08lx unknown\n", h->Type);
  384.         exit(1);
  385.     }
  386.     }
  387. }
  388.  
  389. /*
  390.  *  Dump the stuff, in order
  391.  */
  392.  
  393. void
  394. DumpHunks(fo)
  395. FILE *fo;
  396. {
  397.     short n;
  398.     Hunk *h;
  399.  
  400.     for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
  401.     fwrite(h->Data, 1, h->Len, fo);
  402.     }
  403. }
  404.  
  405.  
  406. long
  407. fgetl(fi)
  408. FILE *fi;
  409. {
  410.     long v;
  411.  
  412.     v = getc(fi) << 24;
  413.     v |= getc(fi) << 16;
  414.     v |= getc(fi) << 8;
  415.     v |= getc(fi);
  416.  
  417.     if (feof(fi)) {
  418.     puts("unexpected EOF");
  419.     exit(1);
  420.     }
  421.     if (DDebug)
  422.     printf("get %08x\n", v);
  423.     return(v);
  424. }
  425.  
  426.